import requests, time
import math
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import execjs
import random
from qq_musicsql import insert_data
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}
session = requests.session()
file = 'c:\\Users\\Administrator\\Desktop\\wangjialei\\'


def download(guid, songmid, cookie_dict):
    data = {"req": {"module": "CDN.SrfCdnDispatchServer", "method": "GetCdnDispatch",
                    "param": {"guid": guid, "calltype": 0, "userip": ""}},
            "req_0": {"module": "vkey.GetVkeyServer", "method": "CgiGetVkey",
                      "param": {"guid": guid, "songmid": [songmid], "songtype": [0], "uin": "0",
                                "loginflag": 1, "platform": "20"}},
            "comm": {"uin": 0, "format": "json", "ct": 24, "cv": 0}}
    # 参数guid来自cookies的pgv_pvid
    url = 'https://u.y.qq.com/cgi-bin/musics.fcg?sign=' + getSign(
        data) + '&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data=%7B%22req%22%3A%7B%22module%22%3A%22CDN.SrfCdnDispatchServer%22%2C%22method%22%3A%22GetCdnDispatch%22%2C%22param%22%3A%7B%22guid%22%3A%22' + guid + '%22%2C%22calltype%22%3A0%2C%22userip%22%3A%22%22%7D%7D%2C%22req_0%22%3A%7B%22module%22%3A%22vkey.GetVkeyServer%22%2C%22method%22%3A%22CgiGetVkey%22%2C%22param%22%3A%7B%22guid%22%3A%22' + guid + '%22%2C%22songmid%22%3A%5B%22' + songmid + '%22%5D%2C%22songtype%22%3A%5B0%5D%2C%22uin%22%3A%220%22%2C%22loginflag%22%3A1%2C%22platform%22%3A%2220%22%7D%7D%2C%22comm%22%3A%7B%22uin%22%3A0%2C%22format%22%3A%22json%22%2C%22ct%22%3A24%2C%22cv%22%3A0%7D%7D'
    print(url)
    r = session.get(url, headers=headers, cookies=cookie_dict)
    purl = r.json()['req_0']['data']['midurlinfo'][0]['purl']
    # 下载歌曲
    if purl:
        url = 'http://ws.stream.qqmusic.qq.com/%s' % (purl)
        print(url)
        r = requests.get(url, headers=headers)
        f = open(file + songmid + '.m4a', 'wb')
        f.write(r.content)
        f.close()
        time.sleep(random.random() * 3)
        r.close()
        return True
    else:
        return False


def getCookies():
    chrome_options = Options()
    # 设置浏览器参数
    # --headless是不显示浏览器启动以及执行过程
    path = 'g://PycharmProject//chromedriver.exe'
    chrome_options.add_argument('--headless')
    driver = webdriver.Chrome(executable_path=path, options=chrome_options)
    # 访问两个URL，QQ网站才能生成Cookies
    driver.get('https://y.qq.com/n/yqq/singer/002J4UUk29y8BY.html#stat=y_new.singerlist.singerpic')
    time.sleep(5)
    # 某个歌手的歌曲信息，用于获取Cookies，因为不是全部请求地址都有Cookies
    url = 'https://y.qq.com/portal/singer_list.html#page=1&area=2&'
    driver.get(url)
    driver.find_element_by_xpath('/html/body/div[1]/div/div[2]/span/a[2]').click()
    time.sleep(5)
    '''for i in range(6):
        time.sleep(i)
        print(i)'''
    cookie = driver.get_cookies()
    driver.quit()
    # Cookies格式化
    cookie_dict = {}
    for i in cookie:
        cookie_dict[i['name']] = i['value']
    return cookie_dict


def get_singer_songs(singermid, cookie_dict):
    data = {"comm": {"ct": 24, "cv": 0}, "singerSongList": {"method": "GetSingerSongList",
                                                            "param": {"order": 1, "singerMid": singermid, "begin": 0,
                                                                      "num": 10},
                                                            "module": "musichall.song_list_server"}}
    url = 'https://u.y.qq.com/cgi-bin/musics.fcg?sign=' + getSign(
        data) + '&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data=%7B%22comm%22%3A%7B%22ct%22%3A24%2C%22cv%22%3A0%7D%2C%22singerSongList%22%3A%7B%22method%22%3A%22GetSingerSongList%22%2C%22param%22%3A%7B%22order%22%3A1%2C%22singerMid%22%3A%22' + singermid + '%22%2C%22begin%22%3A0%2C%22num%22%3A10%7D%2C%22module%22%3A%22musichall.song_list_server%22%7D%7D'
    r = session.get(url, headers=headers)
    songs = eval(str(r.json()['singerSongList']['data']['songList']))
    song_singer = songs[0].get('songInfo').get('singer')[0].get('name')
    song_dict = {}
    for i in songs:
        song = i.get('songInfo')
        song_dict['song_name'] = song['name']
        song_dict['song_album'] = song['album']['name']
        song_dict['song_interval'] = song['interval']
        song_dict['song_songmid'] = song['mid']
        song_dict['song_singer'] = song_singer
        guid = cookie_dict['pgv_pvid']
        info = download(guid, song_dict['song_songmid'], cookie_dict)
        print('success')
        if info:
            insert_data(song_dict)
            song_dict = {}


def get_genre_singer(index, page_list, cookie_dict):
    for page in page_list:
        data = {"comm": {"ct": 24, "cv": 0},
                "singerList": {"module": "Music.SingerListServer", "method": "get_singer_list",
                               "param": {"area": -100, "sex": -100, "genre": -100, "index": index,
                                         "sin": ((page - 1) * 80), "cur_page": page}}}
        url = 'https://u.y.qq.com/cgi-bin/musics.fcg?sign=' + str(getSign(
            data)) + '&loginUin=380468802&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data=%7B%22comm%22%3A%7B%22ct%22%3A24%2C%22cv%22%3A0%7D%2C%22singerList%22%3A%7B%22module%22%3A%22Music.SingerListServer%22%2C%22method%22%3A%22get_singer_list%22%2C%22param%22%3A%7B%22area%22%3A-100%2C%22sex%22%3A-100%2C%22genre%22%3A-100%2C%22index%22%3A' + str(
            index) + '%2C%22sin%22%3A' + str((page - 1) * 80) + '%2C%22cur_page%22%3A' + str(page) + '%7D%7D%7D'
        r = session.get(url)
        for k in r.json()['singerList']['data']['singerlist']:
            singermid = k['singer_mid']
            get_singer_songs(singermid, cookie_dict)


def get_all_singer():
    cookie_dict = getCookies()
    for index in range(1, 28):
        data = {"comm": {"ct": 24, "cv": 0},
                "singerList": {"module": "Music.SingerListServer", "method": "get_singer_list",
                               "param": {"area": -100, "sex": -100, "genre": -100, "index": index, "sin": 0,
                                         "cur_page": 1}}}
        url = 'https://u.y.qq.com/cgi-bin/musics.fcg?sign=' + str(getSign(
            data)) + '&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data=%7B%22comm%22%3A%7B%22ct%22%3A24%2C%22cv%22%3A0%7D%2C%22singerList%22%3A%7B%22module%22%3A%22Music.SingerListServer%22%2C%22method%22%3A%22get_singer_list%22%2C%22param%22%3A%7B%22area%22%3A-100%2C%22sex%22%3A-100%2C%22genre%22%3A-100%2C%22index%22%3A' + str(
            index) + '%2C%22sin%22%3A0%2C%22cur_page%22%3A1%7D%7D%7D'
        r = session.get(url, headers=headers)
        total = r.json()['singerList']['data']['total']
        print(total)
        pagecount = math.ceil(int(total) / 80)
        page_list = [x for x in range(1, pagecount + 1)]
        get_genre_singer(index, page_list, cookie_dict)
        r.close()


def getSign(data):
    with open('g://PycharmProject//src//index.umd.js', 'r', encoding='utf-8') as f:
        js_content = f.read()
        js_exec = execjs.compile(js_content)
        sign = js_exec.call('getSign', data)
        return sign


def myThread(index, cookie_dict):
    data = {"comm": {"ct": 24, "cv": 0},
            "singerList": {"module": "Music.SingerListServer", "method": "get_singer_list",
                           "param": {"area": -100, "sex": -100, "genre": -100, "index": index, "sin": 0,
                                     "cur_page": 1}}}
    url = 'https://u.y.qq.com/cgi-bin/musics.fcg?sign=' + str(getSign(
        data)) + '&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data=%7B%22comm%22%3A%7B%22ct%22%3A24%2C%22cv%22%3A0%7D%2C%22singerList%22%3A%7B%22module%22%3A%22Music.SingerListServer%22%2C%22method%22%3A%22get_singer_list%22%2C%22param%22%3A%7B%22area%22%3A-100%2C%22sex%22%3A-100%2C%22genre%22%3A-100%2C%22index%22%3A' + str(
        index) + '%2C%22sin%22%3A0%2C%22cur_page%22%3A1%7D%7D%7D'
    r = session.get(url, headers=headers)
    total = r.json()['singerList']['data']['total']
    pagecount=math.ceil(int(total)/80)
    page_list=[x for x in range(1,pagecount+1)]
    thread_number=10
    list_interval=math.ceil(len(page_list)/thread_number)
    Thread=ThreadPoolExecutor(max_workers=thread_number)
    for i in range(thread_number):
        start_num=list_interval*i
        if list_interval*(i+1)<=len(page_list):
            end_num=list_interval*(i+1)
        else:
            end_num=len(page_list)
        Thread.submit(get_genre_singer,index,page_list[start_num:end_num],cookie_dict)
def myProcess():
    with ProcessPoolExecutor(max_workers=27) as executor:
        cookie_dict=getCookies()
        for index in range(1,28):
            executor.submit(myThread,index,cookie_dict)


if __name__ == '__main__':
    myProcess()
